home *** CD-ROM | disk | FTP | other *** search
- Subject: v19i100: Usenet sources archiver, Part03/04
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Kent Landfield <ssbell!kent>
- Posting-number: Volume 19, Issue 100
- Archive-name: rkive/part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 4)."
- # Contents: header.c rkive.cf setup.c
- # Wrapped by kent@ssbell on Thu Jun 1 16:19:13 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'header.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'header.c'\"
- else
- echo shar: Extracting \"'header.c'\" \(15302 characters\)
- sed "s/^X//" >'header.c' <<'END_OF_FILE'
- X/*
- X**
- X** This software is Copyright (c) 1989 by Kent Landfield.
- X**
- X** Permission is hereby granted to copy, distribute or otherwise
- X** use any part of this package as long as you do not try to make
- X** money from it or pretend that you wrote it. This copyright
- X** notice must be maintained in any copy made.
- X**
- X** History:
- X** Creation: Tue Feb 21 08:52:35 CST 1989 due to necessity.
- X**
- X*/
- X#ifndef lint
- Xstatic char SID[] = "@(#)header.c 1.1 6/1/89";
- X#endif
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <sys/types.h>
- X#include "article.h"
- X
- Xint its(s1)
- Xregister char *s1;
- X{
- X if (strncmp(s,s1,strlen(s1)) == 0)
- X return(TRUE);
- X return(FALSE);
- X}
- X
- Xint line_type()
- X{
- X if (its("Path: "))
- X return PATH;
- X if (its("From: "))
- X return FROM;
- X if (its("Newsgroups: "))
- X return NEWSGROUP;
- X if (its("Subject: "))
- X return SUBJECT;
- X if (its("Keywords: "))
- X return KEYWORDS;
- X if (its("Date: "))
- X return DATE;
- X if (its("Message-ID: "))
- X return MSG_ID;
- X if (its("Lines: "))
- X return NUMLINES;
- X if (its("Approved: "))
- X return APPROVED;
- X
- X /* The following is the auxilliary headers used by */
- X /* the moderators of the sources groups. In some */
- X /* cases, line checks are done with "historical" */
- X /* auxilliary headers. Most of the moderators have */
- X /* now standardized on comp.sources.unix's format.*/
- X
- X /* Archive header lines for comp.sources.unix */
- X /* for comp.sources.amiga, comp.sources.atari.st, */
- X /* comp.sources.misc, and comp.sources.x. */
- X
- X if (its("Submitted-by: "))
- X return SUBMITTED_BY;
- X if (its("Posting-number: "))
- X return POSTING_NUMBER;
- X if (its("Archive-name: "))
- X return ARCH_NAME;
- X
- X /* Archive header lines for historical purposes */
- X /* once used in comp.sources.misc */
- X
- X if (its("Submitted-By: "))
- X return SUBMITTED_BY;
- X if (its("comp.sources.misc: "))
- X return POSTING_NUMBER;
- X if (its("Archive-Name: "))
- X return ARCH_NAME;
- X
- X /* Archive header lines used in comp.sources.games */
- X /* Archive-name is the same as comp.sources.unix */
- X
- X if (its("Submitted by: "))
- X return SUBMITTED_BY;
- X if (its("Comp.sources.games: "))
- X return POSTING_NUMBER;
- X
- X /* Auxiliary header used as a backward reference */
- X /* to the location of the initially posted sources */
- X /* in the event of a patch. This line only exists */
- X /* if the current article is a patch. */
- X
- X if (its("Patch-To: "))
- X return PATCH_TO;
- X
- X /* Archive header lines for historical purposes */
- X /* once used in mod.sources articles. */
- X
- X if (its("Mod.sources: "))
- X return POSTING_NUMBER;
- X
- X /* The remainder are other types of lines included */
- X /* headers and are includes for formatting output */
- X /* and for potential future use. */
- X
- X if (its("References: "))
- X return REFERENCES;
- X if (its("Organization: "))
- X return ORGANIZATION;
- X if (its("Distribution: "))
- X return DISTRIBUTION;
- X if (its("Xref: "))
- X return XREF;
- X if (its("Expires: "))
- X return EXPIRE;
- X if (its("Article-I.D.: "))
- X return ARTICLEID;
- X if (its("Reply-To: "))
- X return REPLY_TO;
- X if (its("Control: "))
- X return CONTROL;
- X if (its("Sender: "))
- X return SENDER;
- X if (its("Followup-To: "))
- X return FOLLOWUP_TO;
- X if (its("Summary: "))
- X return SUMMARY;
- X if (its("Supersedes: "))
- X return SUPERSEDES;
- X
- X return OTHER;
- X}
- X
- Xdata(hpfield, size, fldname)
- Xchar *hpfield;
- Xint size;
- Xchar *fldname;
- X{
- X register char *ptr;
- X register char *p;
- X char *strncpy();
- X char *strchr();
- X
- X for (ptr = strchr(s, ':'); isspace(*++ptr); )
- X ;
- X if (*ptr != '\0') {
- X (void) strncpy(hpfield, ptr, size - 1);
- X /*
- X * Strip trailing newlines, blanks, and tabs from hpfield.
- X */
- X for (p = hpfield; *p; ++p)
- X ;
- X while (--p >= hpfield && (*p == '\n' || *p == ' ' || *p == '\t'))
- X ;
- X *++p = '\0';
- X }
- X if (debug)
- X (void) fprintf(logfp,"%s: %s\n",fldname, hpfield);
- X}
- X
- Xdump_article()
- X{
- X char *type_str;
- X
- X switch(article.rectype) {
- X case PATCH : type_str = "PATCH";
- X break;
- X case INFORMATIONAL : type_str = "INFORMATIONAL";
- X break;
- X default : type_str = "NORMAL";
- X break;
- X }
- X
- X (void) fprintf(logfp,"Article: [%s]\n",article.newsarticle);
- X (void) fprintf(logfp," newsgroup: [%s]\n",article.newsgroup);
- X (void) fprintf(logfp," filename: [%s]\n",article.filename);
- X (void) fprintf(logfp," volume: [%d]\n",article.volume);
- X (void) fprintf(logfp," issue: [%d]\n",article.issue);
- X (void) fprintf(logfp," record type: [%s]\n", type_str);
- X if (article.rectype == PATCH) {
- X (void) fprintf(logfp," patch volume: [%d]\n",article.patch_volume);
- X (void) fprintf(logfp," patch issue: [%d]\n",article.patch_issue);
- X }
- X (void) fprintf(logfp," reposted: [%s]\n",
- X article.repost ? "YES": "NO");
- X (void) fprintf(logfp," description: [%s]\n",article.description);
- X (void) fprintf(logfp," author's name: [%s]\n",article.author_name);
- X (void) fprintf(logfp," author's logon: [%s]\n\n",article.author_signon);
- X}
- X
- Xinit_article()
- X{
- X article.newsgroup[0] = '\0';
- X article.newsarticle[0] = '\0';
- X article.filename[0] = '\0';
- X article.volume = -1;
- X article.issue = -1;
- X article.rectype = NORMAL;
- X article.repost = FALSE;
- X article.patch_volume = -1;
- X article.patch_issue = -1;
- X article.description[0] = '\0';
- X article.author_name[0] = '\0';
- X article.author_signon[0] = '\0';
- X
- X header.from[0] = '\0'; /* From: */
- X header.path[0] = '\0'; /* Path: */
- X header.nbuf[0] = '\0'; /* Newsgroups: */
- X header.subject[0] = '\0'; /* Subject: */
- X header.ident[0] = '\0'; /* Message-ID: */
- X header.replyto[0] = '\0'; /* Reply-To: */
- X header.references[0] = '\0'; /* References: */
- X header.subdate[0] = '\0'; /* Date: (submission) */
- X header.subtime = 0; /* subdate in secs */
- X header.expdate[0] = '\0'; /* Expires: */
- X header.ctlmsg[0] = '\0'; /* Control: */
- X header.sender[0] = '\0'; /* Sender: */
- X header.followup_to[0] = '\0'; /* Followup-to: */
- X header.distribution[0] = '\0'; /* Distribution: */
- X header.organization[0] = '\0'; /* Organization: */
- X header.numlines[0] = '\0'; /* Lines: */
- X header.intnumlines = 0; /* Integer Version */
- X header.keywords[0] = '\0'; /* Keywords: */
- X header.summary[0] = '\0'; /* Summary: */
- X header.approved[0] = '\0'; /* Approved: */
- X header.xref[0] = '\0'; /* Xref: */
- X header.supersedes[0] = '\0'; /* Supersedes: */
- X header.submitted_by[0] = '\0'; /* Submitted_by: */
- X header.posting_num[0] = '\0'; /* Posting-number: */
- X header.archive_name[0] = '\0'; /* Archive-name: */
- X header.patch_to[0] = '\0'; /* Patch-To: */
- X}
- X
- Xstore_line()
- X{
- X char *strchr(), *strcpy(), *strstrip(), *substr();
- X char *dp, *sp;
- X char wrk[20];
- X
- X switch(line_type()) {
- X
- X case PATH: /*PATH REQUIRED************************/
- X data(header.path, sizeof(header.path), "PATH:");
- X break;
- X
- X case FROM: /*FROM REQUIRED************************/
- X data(header.from, sizeof(header.from), "FROM:");
- X break;
- X
- X case NEWSGROUP: /*NEWSGROUP REQUIRED**************/
- X data(header.nbuf, sizeof(header.nbuf), "NEWSGROUPS:");
- X if ((sp = strchr(s,':')) != NULL) {
- X do {
- X ++sp;
- X } while(!isalpha(*sp));
- X /* remove all crossposting labels */
- X if ((dp = strchr(sp,',')) != NULL)
- X *dp = '\0';
- X (void) strcpy(article.newsgroup,sp);
- X }
- X break;
- X
- X case SUBJECT: /*SUBJECT REQUIRED******************/
- X data(header.subject, sizeof(header.subject), "SUBJECT:");
- X /*
- X ** Save the subject as the description for articles
- X ** that have no volume/issue format. Later in the
- X ** code, this subject line minus the volume/issue
- X ** is stored back in the .description element if
- X ** the volume/issue indicator is found.
- X */
- X (void) strcpy(article.description, header.subject);
- X
- X /*
- X ** Check to see if this article is a repost of
- X ** a previously posted article.
- X */
- X if (substr(s, "REPOST") != NULL)
- X article.repost = TRUE;
- X
- X /*
- X ** Time to get the filename. Assure that it is in a
- X ** volume/issue (v01INF1 or v01i001) format.
- X */
- X if ((sp = strchr(s,'v')) == NULL)
- X return; /* no volume indicator */
- X
- X /*
- X ** Is there a number that follows
- X ** the volume indicator ?
- X */
- X if (*(sp+1) < '0' || *(sp+1) > '9')
- X return; /* The volume number is missing */
- X
- X /*
- X ** Is there a second ':' as well ?
- X */
- X (void) strcpy(article.filename,sp);
- X if ((dp = strchr(article.filename,':')) == NULL)
- X return; /* not in v01i001: format */
- X
- X /*
- X ** terminate the article's filename and
- X ** store the article's description
- X */
- X *dp = '\0';
- X (void) strcpy(article.description, strstrip(++dp));
- X
- X /*
- X ** Store the filename in a work
- X ** buffer so I can stomp on it.
- X */
- X (void) strcpy(wrk, article.filename);
- X
- X /*
- X ** This is an informational posting.
- X */
- X if ((dp = substr(wrk, "INF")) != NULL) {
- X article.rectype = INFORMATIONAL;
- X article.issue = atoi((dp+3));
- X ++sp;
- X *dp = '\0';
- X article.volume = atoi(sp);
- X }
- X
- X /*
- X ** check to see if there is an issue indicator
- X */
- X else if ((dp = strchr(++sp,'i')) == NULL)
- X return; /* proven guilty. not volume/issue format */
- X
- X /* parse the volume from the filename */
- X *dp = '\0';
- X article.volume = atoi(sp);
- X
- X /* parse the issue from the filename */
- X sp = ++dp;
- X while (isdigit(*dp)) ++dp;
- X *dp = '\0';
- X article.issue = atoi(sp);
- X
- X break;
- X
- X case DATE:
- X data(header.subdate, sizeof(header.subdate), "DATE:");
- X break;
- X
- X case EXPIRE:
- X data(header.expdate, sizeof(header.expdate), "EXPIRES:");
- X break;
- X
- X case MSG_ID:
- X data(header.ident, sizeof(header.ident), "MESSAGE-ID:");
- X break;
- X
- X case REPLY_TO:
- X data(header.replyto, sizeof(header.replyto), "REPLY-TO:");
- X break;
- X
- X case REFERENCES:
- X data(header.references, sizeof(header.references), "REFERENCES:");
- X break;
- X
- X case SENDER:
- X data(header.sender, sizeof(header.sender), "SENDER:");
- X break;
- X
- X case FOLLOWUP_TO:
- X data(header.followup_to, sizeof(header.followup_to),"FOLLOWUP-TO:");
- X break;
- X
- X case CONTROL:
- X data(header.ctlmsg, sizeof(header.ctlmsg),"CONTROL:");
- X break;
- X
- X case DISTRIBUTION:
- X data(header.distribution, sizeof(header.distribution),"DISTRIBUTION:");
- X break;
- X
- X case ORGANIZATION:
- X data(header.organization, sizeof(header.organization),"ORGANIZATION:");
- X break;
- X
- X case NUMLINES:
- X data(header.numlines, sizeof(header.numlines),"LINES:");
- X header.intnumlines = atoi(header.numlines);
- X break;
- X
- X case KEYWORDS:
- X data(header.keywords, sizeof(header.keywords), "KEYWORDS:");
- X break;
- X
- X case APPROVED:
- X data(header.approved, sizeof(header.approved), "APPROVED:");
- X break;
- X
- X case SUPERSEDES:
- X data(header.supersedes, sizeof(header.supersedes),"SUPERSEDES:");
- X break;
- X
- X case XREF:
- X data(header.xref, sizeof(header.xref),"XREF:");
- X break;
- X
- X case SUMMARY:
- X data(header.summary, sizeof(header.summary),"SUMMARY:");
- X break;
- X
- X case POSTING_NUMBER:
- X data(header.posting_num, sizeof(header.posting_num), "POSTING_NUMBER:");
- X break;
- X
- X case SUBMITTED_BY:
- X data(header.submitted_by, sizeof(header.submitted_by), "SUBMITTED_BY:");
- X /*
- X ** Save the author's name and sign on if specified
- X ** Can be in any of the following formats:
- X ** kent@ssbell.uucp
- X ** kent@ssbell.uucp (Kent Landfield)
- X ** Kent Landfield <kent@ssbell.uucp>
- X */
- X if ((sp = strchr(s,':')) != NULL) {
- X (void) strcpy(article.author_signon,(sp+2));
- X /*
- X ** Has a name been attached to the signon ?
- X */
- X if ((dp = strchr(article.author_signon,'<')) != NULL) {
- X *(dp-1) = '\0';
- X (void) strcpy(article.author_name, article.author_signon);
- X (void) strcpy(article.author_signon, ++dp);
- X /*
- X ** Save the name, removing the <>.
- X */
- X if ((dp = strchr(article.author_signon,'>')) != NULL)
- X *dp = '\0';
- X }
- X else if ((dp = strchr(article.author_signon,'(')) != NULL) {
- X *(dp-1) = '\0';
- X /*
- X ** Save the name, removing the ().
- X */
- X (void) strcpy(article.author_name, ++dp);
- X if ((dp = strchr(article.author_name,')')) != NULL)
- X *dp = '\0';
- X }
- X }
- X break;
- X
- X case ARCH_NAME:
- X data(header.archive_name,sizeof(header.archive_name),"ARCH_NAME:");
- X break;
- X
- X case PATCH_TO:
- X data(header.patch_to,sizeof(header.patch_to),"PATCH_TO:");
- X article.rectype = PATCH; /* set the article type */
- X
- X /*
- X ** Parse the initially posted article's volume and issue.
- X ** The format of the auxiliary header is
- X **
- X ** Patch-To: Volume 5, Issue 110
- X **
- X ** In the case of multipart initial postings, the Patch-To:
- X ** line points to the first issue.
- X */
- X
- X /*
- X ** First get the volume number.
- X */
- X
- X dp = s;
- X while (*dp && (!isdigit(*dp)))
- X ++dp;
- X sp = dp;
- X while (*dp && (isdigit(*dp)))
- X ++dp;
- X *dp = '\0';
- X article.patch_volume = atoi(sp);
- X
- X /*
- X ** Now get the issue number.
- X */
- X
- X ++dp;
- X while (*dp && (!isdigit(*dp)))
- X ++dp;
- X sp = dp;
- X while (*dp && (isdigit(*dp)))
- X ++dp;
- X *dp = '\0';
- X article.patch_issue = atoi(sp);
- X break;
- X }
- X return;
- X}
- END_OF_FILE
- if test 15302 -ne `wc -c <'header.c'`; then
- echo shar: \"'header.c'\" unpacked with wrong size!
- fi
- # end of 'header.c'
- fi
- if test -f 'rkive.cf' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rkive.cf'\"
- else
- echo shar: Extracting \"'rkive.cf'\" \(9112 characters\)
- sed "s/^X//" >'rkive.cf' <<'END_OF_FILE'
- X#
- X#
- X# @(#)rkive.cf 1.1 6/1/89
- X#
- X# An rkive.cf template.
- X# Copy and edit this to reflect the local archive conditions.
- X# After editing, run ckconfig to display how rkive will interpret
- X# the local specifications.
- X#
- X# The format of the configuration file is as follows:
- X#
- X######################################################################
- X#
- X# Global variables
- X# SPOOLDIR - the base directory for the news subsystem
- X# PROBLEMS - The name of the base directory used to store any
- X# duplicate or "problem" articles. All articles are
- X# stored under this directory in a newsgroup/volume
- X# directory.
- X# TYPE - This is the archive type (or the archive key)
- X# There are 3 possible keys:
- X# Volume-Issue, Archive-Name or Article-Number
- X# These are used to determine if you wish the
- X# articles archived in a
- X# /basedir/amiga/Volume1/v001i22 or
- X# /basedir/amiga/Volume1/sitonit or
- X# /basedir/amiga/Volume1/44 format
- X# PATCHES - This variable determines the way in which patches
- X# are installed into the archive. If the PATCHES
- X# entry is not defined either globally or within
- X# the newsgroup, the article is handled as a regular
- X# article and is stored according to the specified
- X# parameters of the newsgroup. The following are
- X# the valid possible values for the PATCHES variable:
- X# PATCHES=Historical
- X# This is the same as if no PATCHES entry
- X# existed at all. It is useful if Historical
- X# patches archiving is the default but there
- X# are certain newsgroups that have it specified
- X# differently.
- X# PATCHES=Package
- X# Package patches archiving allows the inbound
- X# patch to be placed with the directory with
- X# the initially posted articles. In this manner
- X# all parts and fixes of a package are together
- X# making it easier for software retrieval by
- X# uucp requests and mail request facilities
- X# such as netlib.
- X# MAIL - If specified, all actions are mailed to the
- X# list of users specified. The user names are
- X# a comma separated list. It is not necessary to
- X# specify any users.
- X# OWNER - The unix login name for the owner of the
- X# archive files after they are stored in the archive.
- X# GROUP - The unix group value for the group ownership of
- X# the archive files after they are stored in the
- X# archive.
- X# MODE - The modes of the files residing in the archive.
- X# LOG - The location of the master log in which all
- X# actions are logged.
- X# LOG_FORMAT - The format of the records of the master log file.
- X# See the man page for article for a discussion of
- X# the available selection format capabilities.
- X# INDEX - The location of the master index (if one is kept).
- X# The index can be used to interface with the netlib
- X# source retrieval software facility.
- X# INDEX_FORMAT - The format of the records of the master log file.
- X# See the man page for article for a discussion of
- X# the available selection format capabilities.
- X# COMPRESS - The location of the compression utility if the
- X# files are to be reduced.
- X#
- X######################################################################
- XSPOOLDIR=/usr/spool/news
- XPROBLEMS=/usenet/problems
- XTYPE= Volume-Issue
- XPATCHES=Historical
- XMAIL=kent
- XOWNER=src
- XGROUP=archive
- XMODE=0444
- XLOG=/usenet/archive.log
- XLOG_FORMAT= "%B %T"
- XINDEX= /usenet/index
- XINDEX_FORMAT= "%B %a %T"
- X#COMPRESS=/usr/lbin/compress
- X
- X######################################################################
- X#
- X# Each Newsgroup to be archived has an entry with the following
- X# possible variables. (Note that all variables are not necessary)
- X#
- X# BASEDIR - This is the path to the base directory of the archive
- X# TYPE - This is the archive type (or the archive key)
- X# There are 3 possible keys:
- X# Volume-Issue, Archive-Name or Article-Number
- X# These are used to determine if you wish the articles
- X# archived in a
- X# /basedir/amiga/Volume1/v001i22 or
- X# /basedir/amiga/Volume1/sitonit or
- X# /basedir/amiga/Volume1/44 format
- X# PATCHES - This variable determines the way in which patches
- X# are installed into the archive. If the PATCHES
- X# entry is not defined either globally or within
- X# the newsgroup, the article is handled as a regular
- X# article and is stored according to the specified
- X# parameters of the newsgroup. The following are
- X# the valid possible values for the PATCHES variable:
- X# PATCHES=Historical
- X# This is the same as if no PATCHES entry
- X# existed at all. It is useful if Historical
- X# patches archiving is the default but there
- X# are certain newsgroups that have it specified
- X# differently.
- X# PATCHES=Package
- X# Package patches archiving allows the inbound
- X# patch to be placed with the directory with
- X# the initially posted articles. In this manner
- X# all parts and fixes of a package are together
- X# making it easier for software retrieval by
- X# ftp, uucp requests and mail request facilities
- X# such as netlib.
- X# MAIL - If specified, all actions are mailed to the
- X# list of users specified. The user names are
- X# a comma separated list.
- X# OWNER - The unix login name for the owner of the archive files
- X# after they are stored in the archive.
- X# GROUP - The unix group value for the group ownership of the archive
- X# files after they are stored in the archive.
- X# MODE - The modes of the files residing in the archive.
- X# LOG - The location of the log in which all actions are logged.
- X# LOG_FORMAT - The format of the records of the master log file.
- X# See the man page for article for a discussion of
- X# the available selection format capabilities.
- X# INDEX - The location of the master index (if one is kept).
- X# The index can be used to interface with the netlib
- X# source retrieval software facility.
- X# INDEX_FORMAT - The format of the records of the master log file.
- X# See the man page for article for a discussion of
- X# the available selection format capabilities.
- X# COMPRESS - The location of the compression utility if the files
- X# are to be reduced.
- X#
- X######################################################################
- X$$comp.sources.amiga
- X BASEDIR: /usenet/amiga
- X TYPE: Volume-Issue
- X MAIL: rick
- X LOG: /usenet/amiga/log
- X INDEX: /usenet/amiga/index
- X INDEX_FORMAT: "%B %a %T"
- X
- X$$comp.sources.atari.st
- X BASEDIR: /usenet/atari/st
- X TYPE: Volume-Issue
- X LOG: /usenet/atari/st/log
- X INDEX: /usenet/atari/st/index
- X INDEX_FORMAT: "%B %a %T"
- X
- X$$comp.sources.games
- X BASEDIR: /usenet/games
- X MAIL: rick
- X TYPE: Volume-Issue
- X LOG: /usenet/games/log
- X INDEX: /usenet/games/index
- X INDEX_FORMAT: "%B %a %T"
- X
- X$$comp.sources.mac
- X BASEDIR: /usenet/mac
- X TYPE: Article-Number
- X LOG: /usenet/mac/log
- X INDEX: /usenet/mac/index
- X INDEX_FORMAT: "%O %a %T"
- X
- X$$comp.sources.misc
- X BASEDIR: /usenet/misc
- X TYPE: Volume-Issue
- X MAIL: rick
- X LOG: /usenet/misc/log
- X INDEX: /usenet/misc/index
- X INDEX_FORMAT: "%B %a %T"
- X
- X$$comp.sources.unix
- X BASEDIR: /usenet/unix
- X TYPE: Volume-Issue
- X MAIL: rick
- X LOG: /usenet/unix/log
- X LOG_FORMAT: "%B %a %T"
- X INDEX: /usenet/unix/index
- X INDEX_FORMAT: "%B %a %T"
- X
- X$$comp.sources.x
- X BASEDIR: /usenet/x
- X TYPE: Archive-Name
- X PATCHES: Package
- X MAIL: rick,kent,mark
- X LOG: /usenet/x/log
- X LOG_FORMAT: "%B %a %T"
- X INDEX: /usenet/unix/index
- X INDEX_FORMAT: "%B %a %T"
- X
- X$$alt.sources
- X BASEDIR: /usenet/alt/sources
- X TYPE: Article-Number
- X LOG: /usenet/alt/sources/log
- X LOG_FORMAT: "%O %S"
- X
- X$$alt.sources.amiga
- X BASEDIR: /usenet/alt/sources/amiga
- X TYPE: Article-Number
- X MAIL: rick
- X LOG: /usenet/alt/sources/amiga/log
- X LOG_FORMAT: "%O %S"
- END_OF_FILE
- if test 9112 -ne `wc -c <'rkive.cf'`; then
- echo shar: \"'rkive.cf'\" unpacked with wrong size!
- fi
- # end of 'rkive.cf'
- fi
- if test -f 'setup.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'setup.c'\"
- else
- echo shar: Extracting \"'setup.c'\" \(16190 characters\)
- sed "s/^X//" >'setup.c' <<'END_OF_FILE'
- X/*
- X**
- X** This software is Copyright (c) 1989 by Kent Landfield.
- X**
- X** Permission is hereby granted to copy, distribute or otherwise
- X** use any part of this package as long as you do not try to make
- X** money from it or pretend that you wrote it. This copyright
- X** notice must be maintained in any copy made.
- X**
- X**
- X** History:
- X** Creation: Tue Feb 21 08:52:35 CST 1989 due to necessity.
- X**
- X*/
- X#ifndef lint
- Xstatic char SID[] = "@(#)setup.c 1.1 6/1/89";
- X#endif
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <pwd.h>
- X#include <grp.h>
- X#include <dirent.h>
- X#include "cfg.h"
- X
- X#define GAG(b) ((void) fprintf(errfp,"%s invalid variable, ignoring.\n",b))
- X
- Xchar spooldir[MAXNAMLEN] = { SPOOLDIR };
- Xchar problems_dir[MAXNAMLEN] = { PROBLEMS_DIR };
- X
- Xint default_owner = OWNER;
- Xint default_group = GROUP;
- Xint default_modes = MODES;
- Xint default_type = ARTICLE_NUMBER;
- Xint default_patch_type = HISTORICAL;
- X
- X/*
- X** compress -
- X** Used to determine whether or not articles should be compressed
- X** to save space. The command to execute is stored in compress.
- X*/
- Xchar compress[MAXNAMLEN] = { '\0' };
- X
- X/*
- X** mail -
- X** If specified, all actions logged are mailed to the list of users
- X** specified. The user names are a comma seperated list.
- X*/
- Xchar mail[MAXNAMLEN] = { '\0' };
- X
- X/*
- X** log -
- X** The location of the master log in which all actions are logged.
- X** If not specified, all logged events are printed on stdout.
- X*/
- Xchar log[MAXNAMLEN] = { '\0' };
- X
- X/*
- X** log_format -
- X** The format of each individual log file record. The format is
- X** then filled with information contained in the headers.
- X*/
- Xchar log_format[BUFSIZ] = { '\0' };
- X
- X/*
- X** index -
- X** The location of the master index.
- X*/
- Xchar index[MAXNAMLEN] = { '\0' };
- X
- X/*
- X** index_format -
- X** The format of each individual master index record. The format
- X** is then filled with information contained in the headers.
- X*/
- Xchar index_format[BUFSIZ] = { '\0' };
- X
- Xchar *config_file;
- XFILE *config;
- X
- Xstruct stat stbuf;
- Xstruct passwd *pwent;
- X
- Xchar *strstrip();
- Xchar *strchr();
- Xchar *strcpy();
- Xvoid exit();
- Xstruct passwd *getpwnam();
- X
- Xstruct restricted_dirs {
- X char *dirstr; /* path of restricted directory */
- X};
- X
- Xstatic struct restricted_dirs base_dirs[] = {
- X{ "/" },
- X{ "/etc" },
- X{ "/dev" },
- X{ "/dev/dsk" },
- X{ "/dev/rdsk" },
- X{ "/lib" },
- X{ "/stand" },
- X{ "/usr/adm" },
- X{ "/usr/spool/uucp" },
- X{ NULL },
- X};
- X
- Xsetup_defaults()
- X{
- X char *sp;
- X char *buf;
- X char buffer[BUFSIZ];
- X char mode_str[128];
- X
- X char *sav_format();
- X char *get_compress();
- X char *get_users();
- X FILE *efopen();
- X
- X config = efopen(config_file,"r");
- X
- X num = -1; /* initialize group structure index */
- X
- X while (fgets(buffer, sizeof buffer, config) != NULL) {
- X /* ignore comments and blank lines */
- X if (*buffer == '#' || *buffer == '\n')
- X continue;
- X
- X buf = buffer;
- X
- X /* strip leading spaces and tabs */
- X while(*buf == ' ' || *buf == '\t')
- X ++buf;
- X
- X *(buf+(strlen(buf)-1)) = '\0'; /* remove newline */
- X
- X /* if embedded comments, truncate at the comment */
- X if ((sp = strchr(buf,'#')) != NULL)
- X *sp = '\0';
- X
- X /* check to see if newsgroup entry */
- X
- X if (*buf == '$' && *(buf+1) == '$') {
- X if (++num >= NUM_NEWSGROUPS)
- X error("Maximum number of newsgroups exceeded!!\n",
- X "Please increase the NUM_NEWSGROUPS define...");
- X
- X sp = buf+2;
- X while (*sp && !isspace(*sp))
- X ++sp;
- X *sp = '\0';
- X
- X group[num].owner = default_owner;
- X group[num].group = default_group;
- X group[num].modes = default_modes;
- X group[num].type = default_type;
- X group[num].patch_type = default_patch_type;
- X (void) strcpy (group[num].ng_name, strstrip(buf+2));
- X group[num].location[0] = '\0';
- X group[num].mail_list[0] = '\0';
- X group[num].logfile[0] = '\0';
- X group[num].index[0] = '\0';
- X group[num].logformat[0] = '\0';
- X group[num].indformat[0] = '\0';
- X group[num].compress[0] = '\0';
- X }
- X
- X else if ((sp = strchr(buf,'=')) != NULL) {
- X sp++;
- X /* Global assignment */
- X while (*sp == ' ' || *sp == '\t')
- X sp++;
- X
- X if (!*sp) /* is something still there ? */
- X continue;
- X
- X switch(*buf) {
- X case 'C': (void) strcpy(compress, get_compress(buf, sp));
- X break;
- X case 'G': default_group = get_group(buf, sp);
- X break;
- X case 'I': if (strncmp(buf, "INDEX_FORMAT", 12) == 0)
- X (void) strcpy(index_format, sav_format(sp));
- X else if (strncmp(buf, "INDEX", 3) == 0)
- X (void) strcpy(index, strstrip(sp));
- X else
- X GAG(buf);
- X break;
- X case 'L': if (strncmp(buf, "LOG_FORMAT", 10) == 0)
- X (void) strcpy(log_format, sav_format(sp));
- X else if (strncmp(buf, "LOG", 3) == 0)
- X (void) strcpy(log, strstrip(sp));
- X else
- X GAG(buf);
- X break;
- X case 'M': if (strncmp(buf, "MAIL",4) == 0)
- X (void) strcpy(mail,get_users(sp));
- X else if (strncmp(buf, "MODE",4) == 0)
- X default_modes = correct_modes(sp, mode_str);
- X else
- X error(buf, "invalid global assignment");
- X break;
- X case 'O': default_owner = get_owner(buf, sp);
- X break;
- X case 'P': if (strncmp(buf, "PROBLEMS", 8) == 0)
- X (void) strcpy(problems_dir, strstrip(sp));
- X else
- X default_patch_type = get_patch_type("Global",buf,sp);
- X break;
- X case 'S': get_spooldir(buf, sp);
- X break;
- X case 'T': default_type = get_archive_type("Global", buf, sp);
- X break;
- X default : error("invalid global assignment:", buf);
- X }
- X }
- X else if ((sp = strchr(buf,':')) != NULL) {
- X sp++;
- X /* group variable assignment */
- X while (*sp == ' ' || *sp == '\t')
- X sp++;
- X
- X if (!*sp) /* is something still there ? */
- X continue;
- X
- X switch(*buf) {
- X case 'B': if (strncmp(buf, "BASEDIR",7) == 0)
- X get_archive_basedir(sp);
- X break;
- X case 'C': (void)strcpy(group[num].compress,get_compress(buf,sp));
- X break;
- X case 'G': group[num].group = get_group(buf, sp);
- X break;
- X case 'I': if (strncmp(buf, "INDEX_FORMAT", 12) == 0)
- X (void) strcpy(group[num].indformat,sav_format(sp));
- X else if (strncmp(buf, "INDEX", 3) == 0)
- X (void) strcpy(group[num].index, strstrip(sp));
- X else
- X GAG(buf);
- X break;
- X case 'L': if (strncmp(buf, "LOG_FORMAT", 10) == 0)
- X (void) strcpy(group[num].logformat, sav_format(sp));
- X else if (strncmp(buf, "LOG", 3) == 0)
- X (void) strcpy(group[num].logfile, strstrip(sp));
- X else
- X GAG(buf);
- X break;
- X case 'M': if (strncmp(buf, "MAIL",4) == 0)
- X (void) strcpy(group[num].mail_list, get_users(sp));
- X else if (strncmp(buf, "MODE",4) == 0)
- X group[num].modes = correct_modes(sp, mode_str);
- X else
- X GAG(buf);
- X break;
- X case 'O': group[num].owner = get_owner(buf, sp);
- X break;
- X case 'P': group[num].patch_type = get_patch_type(group[num].ng_name,buf,sp);
- X break;
- X case 'T': group[num].type = get_archive_type(group[num].ng_name, buf, sp);
- X break;
- X default : error("invalid group assignment:", buf);
- X }
- X }
- X else /* no idea what it is */
- X error("unknown line type", buf);
- X }
- X (void) fclose(config);
- X}
- X
- Xerror(msg1,msg2)
- X char *msg1;
- X char *msg2;
- X{
- X (void) fprintf(errfp,"%s: %s %s\n",progname,msg1, msg2);
- X exit(1);
- X}
- X
- X/*
- X** valid_base_directory
- X**
- X** Assure the directory specified in the configuration file
- X** as the base directory for a newsgroup archive is not found
- X** in the table of restricted base directories.
- X**
- X** This kind of checking is almost insulting to me as an
- X** administrator but, enough people asked me to put it in
- X** so "this duds for you"..
- X*/
- X
- Xint valid_base_directory(argstr)
- X char *argstr;
- X {
- X register char *rp;
- X register char *dp;
- X char wpath[MAXNAMLEN];
- X char lastchar;
- X struct restricted_dirs *pt;
- X
- X /*
- X ** First check to see if the base directory is any
- X ** character other than a slash. We need to assure
- X ** that "../../../etc" or ./etc is not allowed. We
- X ** need a valid absolute path with which to do relative
- X ** path addressing. (Have I confused myself yet ?)
- X */
- X
- X if (*argstr != '/')
- X return(FALSE);
- X
- X /*
- X ** Strip the string of duplicate '/'s.
- X ** Also check to assure that the path specified
- X ** does not contain the '..' sequence.
- X */
- X
- X dp = argstr;
- X rp = wpath;
- X lastchar = ' ';
- X
- X while (*dp) {
- X if (*dp != '/' || lastchar != '/') {
- X lastchar = *dp;
- X *rp++ = *dp;
- X }
- X if (*dp == '.' && lastchar == '.') {
- X if ((*(dp+1) == '/') || (*(dp+1) == '\0'))
- X return(FALSE);
- X }
- X ++dp;
- X }
- X *rp = '\0';
- X
- X /*
- X ** strip the string of trailing '/'s so
- X ** I can use the simple checking below.
- X */
- X
- X dp = wpath+(strlen(wpath)-1);
- X while(*dp == '/' && dp > wpath)
- X *dp = '\0';
- X
- X /*
- X ** check if they match
- X */
- X
- X pt = &base_dirs[0];
- X while ((pt->dirstr) != NULL) {
- X
- X if (strcmp(wpath, pt->dirstr) == 0)
- X return(FALSE);
- X
- X pt++;
- X }
- X return(TRUE);
- X}
- X
- Xget_archive_basedir(s)
- Xchar *s;
- X{
- X (void) strcpy(group[num].location, strstrip(s));
- X
- X if (!valid_base_directory(group[num].location))
- X error(group[num].ng_name," - Invalid archive base directory!");
- X}
- X
- Xint correct_modes(s,mode_string)
- Xchar *s;
- Xchar *mode_string;
- X{
- X register int c;
- X register int i;
- X
- X i = 0;
- X (void) sscanf(s, "%s", mode_string);
- X while ((c = *mode_string++) >= '0' && c <= '7')
- X i = (i << 3) + (c - '0');
- X mode_string--;
- X return(i);
- X}
- X
- Xchar *get_compress(buffer,cmd)
- Xchar *buffer;
- Xchar *cmd;
- X{
- X static char *rp;
- X
- X if (!valid_variable(buffer, "COMPRESS", 8))
- X return(NULL);
- X
- X rp = strstrip(cmd);
- X
- X /* need to assure the user has specified */
- X /* a valid executable path. */
- X
- X if (stat(rp, &stbuf) != 0)
- X error("Can't find specified COMPRESS -", rp);
- X
- X return(rp);
- X}
- X
- X
- Xint get_group(buffer, valstr)
- Xchar *buffer;
- Xchar *valstr;
- X{
- X char *wp;
- X struct group *grent;
- X struct group *getgrnam();
- X
- X if (!valid_variable(buffer, "GROUP", 5))
- X return(default_group);
- X
- X /* group specified by names but */
- X /* needs to be numbers */
- X
- X wp = strstrip(valstr);
- X
- X if ((grent = getgrnam(wp)) == NULL)
- X error("Invalid system group:",wp);
- X return(grent->gr_gid);
- X}
- X
- X
- Xint get_owner(buffer, valstr)
- Xchar *buffer;
- Xchar *valstr;
- X{
- X char *wp;
- X
- X if (!valid_variable(buffer, "OWNER", 5))
- X return(default_owner);
- X
- X /* owner specified by names but */
- X /* needs to be numbers */
- X
- X wp = strstrip(valstr);
- X
- X if ((pwent = getpwnam(wp)) == NULL)
- X error("Invalid user:",wp);
- X return(pwent->pw_uid);
- X}
- X
- Xint get_archive_type(ngname, buffer, s)
- Xchar *ngname;
- Xchar *buffer;
- Xchar *s;
- X{
- X int return_type;
- X
- X if (!valid_variable(buffer, "TYPE", 4))
- X return(default_type);
- X
- X if (strcmp(s, "Archive-Name") == 0)
- X return_type = ARCHIVE_NAME;
- X else if (strcmp(s, "Volume-Issue") == 0)
- X return_type = VOLUME_ISSUE;
- X else if (strcmp(s, "Article-Number") == 0)
- X return_type = ARTICLE_NUMBER;
- X else {
- X (void) fprintf(errfp,"%s: %s: %s %s\n", progname,
- X ngname, "Invalid Archive Type:", s);
- X (void) fprintf(errfp,"\tTYPE Must be %s, %s or %s\n",
- X "Archive-Name", "Volume-Issue", "Article-Number");
- X exit(1);
- X }
- X
- X return(return_type);
- X}
- X
- Xint valid_variable(buffer, variable, length)
- Xchar *buffer;
- Xchar *variable;
- Xint length;
- X{
- X if (strncmp(buffer, variable, length) != 0) {
- X GAG(buffer);
- X return(FALSE);
- X }
- X return(TRUE);
- X}
- X
- X
- Xget_spooldir(buffer,s)
- Xchar *buffer;
- Xchar *s;
- X{
- X static char *rp;
- X
- X if (!valid_variable(buffer, "SPOOLDIR", 8))
- X (void) strcpy(spooldir, SPOOLDIR);
- X
- X else {
- X rp = strstrip(s);
- X
- X /* need to assure the user has specified */
- X /* a valid directory path for the base */
- X /* directory for the news subsystem.. */
- X
- X if (stat(rp, &stbuf) != 0)
- X error("Can't find SPOOLDIR -", rp);
- X
- X (void) strcpy(spooldir, rp);
- X }
- X}
- X
- Xchar *get_users(s)
- Xchar *s;
- X{
- X char *strcat();
- X
- X static char users[512];
- X char tmp_users[512];
- X char *list, *name;
- X char *cp, *dp;
- X register int i;
- X
- X /* prepare the string for saving by stripping any spaces */
- X
- X for (i = 0; i < sizeof users; i++)
- X users[i] = '\0';
- X
- X cp = s;
- X dp = users;
- X while (*cp) {
- X if (*cp != ' ' && *cp != '\t')
- X *dp++ = *cp;
- X ++cp;
- X }
- X
- X /* need to check the specified user list */
- X /* to assure that all users are valid */
- X
- X (void) strcpy(tmp_users, users);
- X *users = NULL;
- X
- X name = tmp_users;
- X
- X while (name != NULL) {
- X /* is there additional users specified ? */
- X if ((list = strchr(name,',')) != NULL) {
- X list++;
- X *(list-1) = '\0';
- X }
- X
- X /* check if user is found in passwd file */
- X if ((pwent = getpwnam(name)) != NULL) {
- X if (*users != NULL) {
- X (void) strcat(users, ",");
- X (void) strcat(users, name);
- X }
- X else
- X (void) strcpy(users, name);
- X }
- X else
- X error("Invalid user:",name);
- X name = list;
- X }
- X return(users);
- X}
- X
- X/*
- X** get a specified format from the buffer
- X** Must allow for spaces and tabs so they
- X** need to be passed intact in the format.
- X*/
- Xchar *sav_format(s)
- X char *s;
- X{
- X static char *cp;
- X char *dp;
- X
- X if ((cp = strchr(s,'"')) != NULL &&
- X (dp = strchr(++cp,'"')) != NULL) {
- X *dp = '\0';
- X }
- X else
- X cp = NULL;
- X return(cp);
- X}
- X
- Xint get_patch_type(ngname,buffer, s)
- Xchar *ngname;
- Xchar *buffer;
- Xchar *s;
- X{
- X int return_type;
- X
- X if (!valid_variable(buffer, "PATCHES", 7))
- X return(default_type);
- X
- X if (strcmp(s, "Package") == 0)
- X return_type = PACKAGE;
- X else if (strcmp(s, "Historical") == 0)
- X return_type = HISTORICAL;
- X else {
- X (void) fprintf(errfp,"%s: %s: %s %s\n", progname,
- X ngname, "Invalid Patches Type:", s);
- X (void) fprintf(errfp,"\tTYPE Must be %s, or %s\n",
- X "Historical", "Package");
- X exit(1);
- X }
- X return(return_type);
- X}
- END_OF_FILE
- if test 16190 -ne `wc -c <'setup.c'`; then
- echo shar: \"'setup.c'\" unpacked with wrong size!
- fi
- # end of 'setup.c'
- fi
- echo shar: End of archive 3 \(of 4\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 4 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-